#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2020-07-23

@author: zhuyu
"""

import re
import time
import xlwt
import subprocess
# import commands
import baseFunc
import threading
import logging

MEM_DIRS = r'D:\python\Scripts\project\PY27TEST\report'  # 路径自定义
RUN_APP_LIST = [
    'com.alipay.iot.master',
    'com.alipay.iot.ic',
    'com.alipay.iot.service',
    'com.alipay.iot.osupdate',
    'com.alipay.iot.systemcommand',
    'com.alipay.iot.osupdate',
    'com.alipay.mapp.content.service',
    'com.alipay.iot.settings',
    'zoloz.phone.android.alipay.com.dragonfly',
    'com.alipay.zoloz.smile',
    'com.alipay.iot.xpaas',
    'com.alipay.mapp.content.service',
    'com.alipay.mapp.content.display',
    'com.alipay.iot.profile',
    'com.alipay.iot.merchantplugin',
    'com.alipay.iot.miniapp.shell',
    'com.alipay.iot.bootwizard'
]


def getAlipayApp():
    alipay_info = {}
    cmds = 'adb shell "ps | grep alipay"'  # 原先指令adb shell ps | grep alipay不支持，修改cmd指令为adb shell "ps | grep alipay"
    # lines = subprocess.getoutput(cmds).split('\n')
    lines = subprocess.getoutput(cmds).split('\n')  # python3中无commands，修改为subprocess
    # print(lines)
    for line in lines:
        app_info = line.split(" ")
        while '' in app_info:
            app_info.remove('')
        app_name = app_info[-1]
        if ':' not in app_name:  # 获取所有蚂蚁应用列表
            alipay_info[app_name] = app_info[1]
    # print(alipay_info)
    # print(type(alipay_info))
    return alipay_info


def proc_osmemory():
    mem_dict = {}
    try:
        mem_lines = subprocess.getoutput('adb shell cat /proc/meminfo')
        for mem in mem_lines.split('\n'):
            meminfo = mem.split(':')
            mem_dict[meminfo[0]] = meminfo[1].strip()
        time.sleep(2)
    except Exception as ex:
        logging.exception(ex)
    return mem_dict


def get_app_pid(appname):
    app_pid = 0
    lines = subprocess.getoutput("adb shell ps |grep {} ".format(appname)).split('\n')
    if lines == ['']:
        return app_pid
    for line in lines:
        pro_info = line.split(' ')
        while '' in pro_info:
            pro_info.remove('')
        app_pid = pro_info[1]
        appname_temp = pro_info[-1].strip('\n')
        if appname == appname_temp:
            return app_pid


def getAlipayCpu(pid):
    app_cpu = 0.0  # 默认为0，当无此进程时为0，无cpu开销
    if pid == 0:
        return app_cpu
    cmd = "adb shell top  -n 1 |grep {}".format(pid)
    lines = subprocess.getoutput(cmd).split('\n')
    for line in lines:
        lis = line.split(' ')
        while '' in lis:  # 将list中的空元素删除
            lis.remove('')
        if len(lis) < 1:
            break
        if pid == lis[0]:
            app_cpu = float(lis[4].strip('%'))
    return app_cpu


def getAppMemory(app_name):
    cmds = "adb shell dumpsys meminfo {}".format(app_name)
    total = "TOTAL"
    mem_data = 0  # 获取失败时，例如进程挂了，直接返回0
    try:
        lines = subprocess.getoutput(cmds).split('\n')
        for line in lines:
            if re.findall(total, line):  # 找到TOTAL 这一行
                lis = line.split(" ")  # 将这一行，按空格分割成一个list
                while '' in lis:  # 将list中的空元素删除
                    lis.remove('')
                # print '{}:{}'.format(app_name, lis[1])
                mem_data = int(lis[1])
    except Exception as ex:
        logging.exception(ex)
    finally:
        return mem_data


def saveMemoryData(loop_num):
    book = xlwt.Workbook(encoding='utf-8')
    # 创建一个名为sheetname的表单
    sheet = book.add_sheet('data')
    # 将工作簿以bookname命名并保存
    apps_info = getAlipayApp()
    apps = list(apps_info.keys())  # python3的dict_keys需要转list
    app_table = {}
    j = 1  # 从第二行开始写入内存数据
    try:
        sheet.write(0, 0, 'usedram')
        sheet.write(0, 1, 'available')
        for i in range(2, len(apps) + 2):  # 从第三列开始写入列名称
            sheet.write(0, i, apps[i - 2])  # 第一行按应用名写入
            app_table[apps[i - 2]] = i  # 记录应用名和列的关系，防止错乱
        sheet.write(0, len(apps) + 2, "alipay_total")
        while j < loop_num:
            alipay_total = 0
            osm = proc_osmemory()
            if len(osm) > 3:
                memtotal = int(osm['MemTotal'].split(' ')[0])  # 获取总的内存
                available = int(osm['MemAvailable'].split(' ')[0])
                usedram = memtotal - available  # 获取当前剩余内存
            else:
                available = 0
                usedram = 0
            sheet.write(j, 0, usedram)
            sheet.write(j, 1, available)
            for app in apps:
                app_mem = getAppMemory(app)
                sheet.write(j, app_table[app], app_mem)  # 写入内存数据
                alipay_total = alipay_total + app_mem
            sheet.write(j, len(apps) + 2, alipay_total)
            print('第{}次：获取内存数据'.format(j))
            j = j + 1
    except Exception as ex:
        logging.exception(ex)
    finally:
        book.save('{}AlipayMem_{}.xls'.format(MEM_DIRS, baseFunc.gettimestr()))


def saveCpuData(loop_num):
    book = xlwt.Workbook(encoding='utf-8')
    # 创建一个名为sheetname的表单
    sheet = book.add_sheet('data')
    # 将工作簿以bookname命名并保存
    apps_info = getAlipayApp()
    # print("apps_info是：",apps_info)
    # time.sleep(1)
    apps = list(apps_info.keys())  # python3的dict_keys需要转list
    # print("apps是：", apps)
    # print(type(apps))
    # time.sleep(1)
    app_table = {}
    j = 1  # 从第二行开始写入CPU数据
    try:
        for i in range(len(apps)):  # 从第三列开始写入列名称
            sheet.write(0, i, apps[i])  # 第一行按应用名写入
            app_table[apps[i]] = i  # 记录应用名和列的关系，防止错乱
        sheet.write(0, len(apps), "alipay_total")
        while j < loop_num:
            alipay_total = 0
            for app in apps:
                cpu_data = getAlipayCpu(apps_info[app])
                sheet.write(j, app_table[app], cpu_data)
                alipay_total = alipay_total + cpu_data
            sheet.write(j, len(apps), alipay_total)
            print('第{}次：获取CPU数据'.format(j))
            j = j + 1
    except Exception as ex:
        logging.exception(ex)
    finally:
        book.save('{}AlipayCPU_{}.xls'.format(MEM_DIRS, baseFunc.gettimestr()))


def runThreadMonitor(loop_num):  # 多线程获取内存和CPU，至于python的伪多线程的时间误差，可以接受
    lines = []
    while len(lines) < 1:
        # lines = subprocess.getoutput('adb devices').split('\n')
        lines = subprocess.getoutput('adb devices')
        lines = re.findall(r'CMPC\d+', lines, re.S)  # 执行adb devices出现List of...，使用正则筛选devices名
        # print('请检查设备是否连接！！！！')
        # time.sleep(3)
    t1 = threading.Thread(target=saveMemoryData, args=(loop_num,))
    t2 = threading.Thread(target=saveCpuData, args=(loop_num,))
    t1.start()
    t2.start()


if __name__ == '__main__':
    # saveMemoryData(1000)
    # print getAlipayCpu('1472111')
    runThreadMonitor(2)  # 修改线程数，两个线程代表执行一次获取内存数据和获取cpu数据
